package owlapps2012.owlToSql.events.p4;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;

import javax.swing.AbstractButton;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;
import org.coode.owlapi.manchesterowlsyntax.ManchesterOWLSyntaxEditorParser;
import org.protege.editor.owl.model.inference.OWLReasonerManager;
import org.protege.editor.owl.model.inference.ReasonerStatus;
import org.protege.editor.owl.model.inference.ReasonerUtilities;
import org.protege.editor.owl.ui.renderer.EventRendering;
import org.protege.editor.owl.ui.view.cls.AbstractOWLClassViewComponent;
import org.semanticweb.owlapi.expression.ParserException;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyRenameException;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.util.SimpleShortFormProvider;

import owlapps2012.base.DLQueryParser;
import owlapps2012.owlToSql.base.CompoundCategoryTransformer;
import owlapps2012.owlToSql.base.DynamicDbAppConfig;
import owlapps2012.owlToSql.base.OwlToSqlTransformationException;
import owlapps2012.owlToSql.base.TemporalExpressionAnalyzer;
import owlapps2012.owlToSql.base.TextProcessingUtils;
import owlapps2012.owlToSql.events.EventsTransformer;
import uk.ac.manchester.cs.owl.owlapi.mansyntaxrenderer.ManchesterOWLSyntaxOWLObjectRendererImpl;


/**
* Author: Piotr Nowara<br>
* piotrnowara@gmail.com<br>
* code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)<br>
* copyright 2013, Piotr Nowara<br>
*/
public class LinkedFactsDBInteractionPanel extends AbstractOWLClassViewComponent implements ActionListener
{
	/**
	 * VERSION: 20150103_1
	 * 
	 */
	private static final long serialVersionUID = -3963830520410216389L;

	private static Logger log = Logger.getLogger(ClassificationCategoriesView.class);
	
	private static final String configFileName = "EventsToSQLP4Transformer.properties";
	private static final String dbConfigFileName = "LinkedFactsP4DbConfig.properties";
	
	private static final String DB_USER_PARAM_NAME = "DbUser";
	private static final String DB_SRC_SCHEMA_PARAM_NAME = "DbSrcSchema";
	private static final String DB_APP_SCHEMA_PARAM_NAME = "DbAppSchema";
	private static final String DB_CONN_URL_PARAM_NAME = "DbConnURL";
	private static final String DB_DRIVER_PARAM_NAME = "DbDriver";
	private static final String DB_CATEGORY_SEQUENCE = "CategoryTableSQLSequence";
	private static final String DB_VERSION_CHCECKING = "CategoryVersionChecking";

	
//	private static final String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";


	protected JTable clTable, resultsTable;
	protected Connection conn;
	protected JButton exportSelectedCategory, exportHierarchy, exportAllNewCategories, classify, refresh, showMoreResults, refreshResults;
	protected OWLClass selectedClass;
	
	protected String dbUserName;
	protected String dbSrcSchema;
	protected String dbAppSchema;
	protected String dbDriverName;
	protected String dbConnURL;
	protected String dbCategorySequenceName;
	protected LinkedFactsDBInteractionDbTools dbTools;

	protected JPanel clButtonPane;
	protected JTabbedPane tabbedPane;
	protected JPanel resButtonPane;

	protected DynamicDbAppConfig lfConfig;
	protected Properties dbConfig;
	protected OWLOntology activeOntology;
	protected OWLAnnotationProperty sqlSelectAP;
	protected ManchesterOWLSyntaxOWLObjectRendererImpl renderer;
	protected OWLAnnotationProperty backwardValidityAP;
	protected OWLAnnotationProperty forwardValidityAP;
	protected OWLAnnotationProperty baseCategoryAP;
	protected OWLReasoner reasoner;
	protected EventsTransformer temporalCategoryTransformer;
	protected CompoundCategoryTransformer compoundCategoryTransformer;
	protected ArrayList<OWLClass> listOfSuccesfullyTransformedCategories = new ArrayList<OWLClass>();
	protected ArrayList<OWLClass> listOfNotTransformedCategories = new ArrayList<OWLClass>();
	protected HashSet<String> alreadyCheckedCombinations;
	protected String jarDirectory;
	protected boolean versionChceckingMode;
	private DLQueryParser dlQueryParser;

    // create the GUI
    public void initialiseClassView() throws Exception
    {
    	setLayout(new BorderLayout(6, 6));
        clTable = new JTable();
        resultsTable = new JTable();
        clTable.setEnabled(true);
        resultsTable.setEnabled(true);
        this.clButtonPane = new JPanel();
        this.resButtonPane = new JPanel();
        clTable.setColumnSelectionAllowed(true);
        resultsTable.setColumnSelectionAllowed(true);
        clButtonPane.setSize(new Dimension(700, 100));
        clButtonPane.setMaximumSize(new Dimension(700, 100));
        clTable.setMinimumSize(new Dimension(1700, 700));
        resultsTable.setMinimumSize(new Dimension(1700, 400));

//        add(buttonPane, BorderLayout.NORTH);
//        add(new JScrollPane(table));
        
        JPanel clPanel = new JPanel();
        JPanel resPanel = new JPanel();
        clPanel.setLayout(new BoxLayout(clPanel, BoxLayout.Y_AXIS));
        resPanel.setLayout(new BoxLayout(resPanel, BoxLayout.Y_AXIS));
        clPanel.add(clButtonPane);
        clPanel.add(new JScrollPane(clTable));
        resPanel.add(new JScrollPane(resultsTable));
        resPanel.add(resButtonPane);
//        clPanel.add(clButtonPane, BorderLayout.NORTH);
//        clPanel.add(new JScrollPane(clTable), BorderLayout.CENTER);
//        resPanel.add(new JScrollPane(resultsTable), BorderLayout.NORTH);
//        resPanel.add(resButtonPane, BorderLayout.SOUTH);
        
        
        tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Classifications", clPanel);
        tabbedPane.addTab("Results", resPanel);

        add(tabbedPane);
        
        exportSelectedCategory = new JButton("Export selected category");
        exportSelectedCategory.setVerticalTextPosition(AbstractButton.CENTER);
        exportSelectedCategory.setHorizontalTextPosition(AbstractButton.LEADING); //aka LEFT, for left-to-right locales
        exportSelectedCategory.setActionCommand("Export selected category");
 
        exportHierarchy = new JButton("Export hierarchy");
        exportHierarchy.setVerticalTextPosition(AbstractButton.BOTTOM);
        exportHierarchy.setHorizontalTextPosition(AbstractButton.CENTER);
        exportHierarchy.setActionCommand("Export hierarchy");
 
        exportAllNewCategories = new JButton("Export all new categories");
        exportAllNewCategories.setVerticalTextPosition(AbstractButton.BOTTOM);
        exportAllNewCategories.setHorizontalTextPosition(AbstractButton.CENTER);
        exportAllNewCategories.setActionCommand("Export all new categories");
        
        classify = new JButton("Classify");
        //Use the default text position of CENTER, TRAILING (RIGHT).
        classify.setActionCommand("Classify");
       	classify.setEnabled(chceckIfClassificationEnabled());
       
        if(clTable.getRowCount() == 0)
        {
        	exportSelectedCategory.setEnabled(true);
        }
        
        refresh = new JButton("Refresh");
        //Use the default text position of CENTER, TRAILING (RIGHT).
        refresh.setActionCommand("Refresh");
        
        showMoreResults = new JButton("Show more results");
        showMoreResults.setActionCommand("Show more results");
        refreshResults = new JButton("Refresh results");
        refreshResults.setActionCommand("Refresh results");
        
        clButtonPane.add(exportSelectedCategory);
        clButtonPane.add(exportHierarchy);
        clButtonPane.add(classify);
        clButtonPane.add(refresh);
        clButtonPane.add(exportAllNewCategories);
        resButtonPane.add(showMoreResults);
        resButtonPane.add(refreshResults);

        
        refresh.addActionListener(this);
        showMoreResults.addActionListener(this);
        classify.addActionListener(this);
        exportHierarchy.addActionListener(this);
//        countFacts.addActionListener(this);
        exportSelectedCategory.addActionListener(this);
        exportAllNewCategories.addActionListener(this);
        refreshResults.addActionListener(this);
        this.clButtonPane.setVisible(true);
        
        
        readConfiguration();
        initDbConnection();//initialize database connection
        initOWLObjects();
        renderer = new ManchesterOWLSyntaxOWLObjectRendererImpl();
        this.temporalCategoryTransformer = new EventsTransformer(this.lfConfig);//requires readConfiguration()
        this.compoundCategoryTransformer = new CompoundCategoryTransformer(this.lfConfig);

    }
    
    private void readConfiguration() throws Exception 
    {
    	this.jarDirectory = new File(LinkedFactsDBInteractionPanel.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath();
    	try 
    	{
    		this.lfConfig = new DynamicDbAppConfig(this.jarDirectory.concat(File.separator).concat(configFileName), this.jarDirectory.concat(File.separator).concat(dbConfigFileName));
			this.dbConfig = new Properties();
			this.dbConfig.load(new FileInputStream(jarDirectory.concat(File.separator).concat(dbConfigFileName)));
    	} 
    	catch (Exception e) 
    	{
    		throw new Exception("Unable to read configuration file!", e);
    	}
    	
		this.dbUserName = this.dbConfig.getProperty(DB_USER_PARAM_NAME);
		if(this.dbUserName == null)
			throw new Exception("Config file does not specify database user name!");
		this.dbSrcSchema = this.dbConfig.getProperty(DB_SRC_SCHEMA_PARAM_NAME);
		if(this.dbSrcSchema == null)
			throw new Exception("Config file does not specify source database schema name!");
		this.dbDriverName = this.dbConfig.getProperty(DB_DRIVER_PARAM_NAME);
		if(this.dbDriverName == null)
			throw new Exception("Config file does not specify JDBC driver!");
		this.dbConnURL = this.dbConfig.getProperty(DB_CONN_URL_PARAM_NAME);
		if(this.dbConnURL == null)
			throw new Exception("Config file does not specify JDBC connection URL!");
		this.dbAppSchema = this.dbConfig.getProperty(DB_APP_SCHEMA_PARAM_NAME, "LINKEDFACTS");
		this.dbCategorySequenceName = this.dbConfig.getProperty(DB_CATEGORY_SEQUENCE, "CATEGORY_SEQ");
		this.versionChceckingMode = this.dbConfig.getProperty(DB_VERSION_CHCECKING, "N").equals("Y");

	}

	private boolean chceckIfClassificationEnabled()
    {
    	//TODO configurable!
		return true;
	}
	
//	private void initDbConnection() throws Exception 
//    {
//   		Connection conn = null;
//    	String dbPasswd = showPasswordPanel("Enter the password for accesing the database");
//		if(dbPasswd != null)
//	        try 
//			{
//	        	conn = getUserProvidedConnection(this.lfConfig.getDbConnURL(), this.lfConfig.getDbDriverName(), this.lfConfig.getDbUserName(), dbPasswd);
////	        	conn.setAutoCommit(true);
//	        	conn.setAutoCommit(false);
//			} 
//	        catch (Exception e)
//			{
//				JOptionPane.showMessageDialog(this.getOWLWorkspace(),
//		                "Error while attempting to establish a database connection: "+e.getMessage(),
//		                "Error Message",
//		                JOptionPane.ERROR_MESSAGE);
//				this.initDbConnection();
//			}
//		
//    	if(this.lfConfig.getSqlType() == null)
//			throw new Exception("No SQL type specified!");
//		if(this.lfConfig.getSqlType().getName().equals("DB2"))
//			this.dbTools = new LinkedFactsDBInteractionDB2Tools(conn);
//		else if(this.lfConfig.getSqlType().getName().equals("POSTGRES"))
//			this.dbTools = new LinkedFactsDBInteractionPostgresDbTools(conn);
//		else
//			throw new Exception("Additional configuration needed for "+this.lfConfig.getSqlType().getName());
//	}

	private void initDbConnection() throws Exception 
    {
   		Connection conn = null;
   		String[] dbSignOnData = showDatabeseSignOnPanel(this.lfConfig.getDbUserName());
   		String dbUser = dbSignOnData[0];
   		String dbPasswd = dbSignOnData[1];
		if(dbPasswd != null && dbUser != null)
	        try 
			{
	        	conn = getUserProvidedConnection(this.lfConfig.getDbConnURL(), this.lfConfig.getDbDriverName(), dbUser, dbPasswd);
//	        	conn.setAutoCommit(true);
	        	conn.setAutoCommit(false);
			} 
	        catch (Exception e)
			{
				JOptionPane.showMessageDialog(this.getOWLWorkspace(),
		                "Error while attempting to establish a database connection: "+e.getMessage(),
		                "Error Message",
		                JOptionPane.ERROR_MESSAGE);
				this.initDbConnection();
			}
		
    	if(this.lfConfig.getSqlType() == null)
			throw new Exception("No SQL type specified!");
		if(this.lfConfig.getSqlType().getName().equals("DB2"))
			this.dbTools = new LinkedFactsDBInteractionDB2Tools(conn);
		else if(this.lfConfig.getSqlType().getName().equals("POSTGRES"))
			this.dbTools = new LinkedFactsDBInteractionPostgresDbTools(conn);
		else
			throw new Exception("Additional configuration needed for "+this.lfConfig.getSqlType().getName());
	}

//	private void initDbObjects() throws Exception 
//    {
//		try
//		{
//			String jarDirectory = new File(EventsToSQLP4Transformer.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath();
//			String configFilePath = jarDirectory.concat(File.separator).concat("LinkedFactsP4DbConfig.properties");
//			this.dbConfig = new Properties();
//			this.dbConfig.load(new FileInputStream(configFilePath));
//		} catch (Exception e) {
//			e.printStackTrace();
//			throw e;
//		}
//		this.dbUserName = this.dbConfig.getProperty(DB_USER_PARAM_NAME);
//		if(this.dbUserName == null)
//			throw new Exception("Config file does not specify database user name!");
//		this.dbSrcSchema = this.dbConfig.getProperty(DB_SRC_SCHEMA_PARAM_NAME);
//		if(this.dbSrcSchema == null)
//			throw new Exception("Config file does not specify source database schema name!");
//		this.dbDriverName = this.dbConfig.getProperty(DB_DRIVER_PARAM_NAME);
//		if(this.dbDriverName == null)
//			throw new Exception("Config file does not specify JDBC driver!");
//		this.dbConnURL = this.dbConfig.getProperty(DB_CONN_URL_PARAM_NAME);
//		if(this.dbConnURL == null)
//			throw new Exception("Config file does not specify JDBC connection URL!");
//		this.dbAppSchema = this.dbConfig.getProperty(DB_APP_SCHEMA_PARAM_NAME, "LINKEDFACTS");
//		this.dbCategorySequenceName = this.dbConfig.getProperty(DB_CATEGORY_SEQUENCE, "CATEGORY_SEQ");
//		
//		try 
//		{
//			String configFileName = EventsToSQLP4Transformer.class.getSimpleName().concat(".properties");
//			String jarDirectory = new File(EventsToSQLP4Transformer.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath();
//			String configFilePath = jarDirectory.concat(File.separator).concat(configFileName);
//			lfConfig = new Properties();
//			lfConfig.load(new FileInputStream(configFilePath));
//		} catch (Exception e) {
//			e.printStackTrace();
//			throw e;
//		}
//	}
	
	private void initOWLObjects() throws Exception
	{
		activeOntology =  getOWLModelManager().getActiveOntology();
		sqlSelectAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#sqlSelect")));
		baseCategoryAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#baseCategory")));
		backwardValidityAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#backwardValidity")));
		forwardValidityAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#forwardValidity")));
		dlQueryParser = new DLQueryParser(activeOntology, new SimpleShortFormProvider());
//		OWLReasonerManager reasonerManager = getOWLModelManager().getOWLReasonerManager();
//		ReasonerUtilities.warnUserIfReasonerIsNotConfigured(getOWLWorkspace(), reasonerManager);
//		if(reasonerManager.getReasonerStatus() != ReasonerStatus.INITIALIZED)
//			throw new Exception("No reasoner has been initialized!");
//	
//        reasoner = reasonerManager.getCurrentReasoner();
//        reasoner.precomputeInferences(new InferenceType[0]);
	}
    
    public void actionPerformed(ActionEvent e) 
    {
//    	TODO obsługa NULLi (gdy naciskamy klaswisz bez zaznaczenia)
    	log.info("Action: "+e);
        if("Refresh".equals(e.getActionCommand())) 
        {
        	log.info("Refreshing: "+selectedClass);
            this.updateView(this.selectedClass);
        } 
        else if("Classify".equals(e.getActionCommand()))
        {
    		if(this.selectedClass != null)
				try 
    			{
					if(this.dbTools.dbChceckIfCategoryAlreadyExported(this.selectedClass))
						this.initClassification(this.selectedClass);
					else
						throw new Exception("Category has to be exported before classification!\n Use 'Export selected category' button ant then 'Classify'.");
					JOptionPane.showMessageDialog(this,
			                "Classification has been initialized.",
			                "Classify",
			                JOptionPane.INFORMATION_MESSAGE);
					this.updateView(this.selectedClass);//auto-refresh
				} 
    			catch (Exception e1) 
    			{
					log.error(e1);		
					JOptionPane.showMessageDialog(this,
			                "Classification not possible - reason: "+e1.getMessage(),
			                "Classify",
			                JOptionPane.ERROR_MESSAGE);
				}
        }
        else if("Export hierarchy".equals(e.getActionCommand()))
        {
        	try 
        	{
        		initReasoner();
        		this.exportHierarchy();
//        		if(versionChceckingMode)
//        			this.exportNewVersionsOfRelatedCategories();
        		dbTools.dbCommit();
        		JOptionPane.showMessageDialog(this,
		                "Categories have been exported - check log for details",
		                "Export hierarchy",
		                JOptionPane.INFORMATION_MESSAGE);
			} 
        	catch (Exception e1) 
			{
				log.error(e1);		
				JOptionPane.showMessageDialog(this,
		                "Export interrupted.\nReason: "+e1.getMessage(),
		                "Export hierarchy",
		                JOptionPane.ERROR_MESSAGE);
			}
        }
        else if("Export all new categories".equals(e.getActionCommand()))
        {
        	try 
        	{
        		initReasoner();
        		this.exportAllNewCategories();
//        		if(versionChceckingMode)
//        			this.exportNewVersionsOfRelatedCategories();
				dbTools.dbCommit();
        		JOptionPane.showMessageDialog(this,
        				"Categories have been exported - check log for details",
        				"Export all new categories",
        				JOptionPane.INFORMATION_MESSAGE);
        	} 
        	catch (Exception e1) 
        	{
        		log.error(e1);		
        		JOptionPane.showMessageDialog(this,
        				"Export interrupted.\nReason: "+e1.getMessage(),
        				"Export all new categories",
        				JOptionPane.ERROR_MESSAGE);
        	}
        }
        else if("Export selected category".equals(e.getActionCommand()))
        {
        	try 
        	{
        		if(!this.dbTools.dbChceckIfCategoryAlreadyExported(this.selectedClass))
        		{
            		initReasoner();
					this.listOfSuccesfullyTransformedCategories.clear();
        			this.exportCategory(this.selectedClass);
//        		    if(versionChceckingMode)
//        		    	this.exportNewVersionsOfRelatedCategories();
    				dbTools.dbCommit();

        			JOptionPane.showMessageDialog(this,
    		                "Selected category has been exported",
    		                "Export selected category",
    		                JOptionPane.INFORMATION_MESSAGE);
        		}
        		else
        			JOptionPane.showMessageDialog(this,
    			            "Selected category has already been exported.",
    			            "Export selected category",
    			            JOptionPane.INFORMATION_MESSAGE);
        		
        		this.exportSelectedCategory.setEnabled(false);
			} 
        	catch (Exception e1) 
			{
				log.error(e1);		
				JOptionPane.showMessageDialog(this,
		                "Unable to export category "+this.selectedClass.getIRI().getFragment()+"\nReason: "+e1.getMessage(),
		                "Export selected category",
		                JOptionPane.WARNING_MESSAGE);
			}
        }
        else if("Show more results".equals(e.getActionCommand()))
        {
        	log.info("show more results... ");
        	ClassificationResults clRes = null;
            try 
            {
//            	if(this.resultsTable.getRowCount() != 100)
//            	{
//            		log.warn("Expected 100 rows in a results table - encountered: "+this.resultsTable.getRowCount());
//            		return;
//            	}
            	String srcTableName = this.lfConfig.getDomainClassMapping(getCategoryType(selectedClass)).getTableName();
            	if(srcTableName == null)
            		throw new Exception("Unable to determine source table for "+selectedClass);
            	String resultsTableName = getResultsTableName(this.selectedClass);
            	if(resultsTableName == null)
            		throw new Exception("Unable to determine results table for "+selectedClass);
//            	clRes = this.dbTools.dbGetResults(resultsTableName, Long.parseLong((String)clTable.getValueAt(clTable.getRowCount()-1, 0)), srcTableName, Integer.parseInt((String)this.resultsTable.getValueAt(this.resultsTable.getRowCount()-1, 0)));
            	clRes = this.dbTools.dbGetResults(resultsTableName, (Long)clTable.getValueAt(clTable.getRowCount()-1, 0), srcTableName, Integer.parseInt((String)this.resultsTable.getValueAt(this.resultsTable.getRowCount()-1, 0)));
			}
            catch (Exception e1) 
            {
                String errInfo = "Unable to retrieve data about "+ selectedClass;
                log.error(errInfo, e1);
            }
            if(clRes != null)
            	renderResults(clRes);
        }
        else if("Refresh results".equals(e.getActionCommand()))
        {
        	this.updateView(this.selectedClass);
        }
    }
    
	private void exportNewVersionsOfRelatedCategories() throws SQLException, OwlToSqlTransformationException, OWLOntologyRenameException, ParserException 
	{
		ArrayList<OWLClass> listOfCategoriesToCheck = new ArrayList<OWLClass>(listOfSuccesfullyTransformedCategories);
		ArrayList<String> listOfDependentCategories = new ArrayList<String>();
		log.info("listOfSuccesfullyTransformedCategories: "+listOfCategoriesToCheck);
		log.info(listOfSuccesfullyTransformedCategories.size());
		log.info("listOfCategoriesToCheck: "+listOfCategoriesToCheck);
		log.info(listOfCategoriesToCheck.size());
		for(int i=0;i<listOfCategoriesToCheck.size();i++)
		{
			OWLClass cat = listOfCategoriesToCheck.get(i);
			String catName = cat.getIRI().getFragment();
			if(!catName.contains("__v"))
				throw new OwlToSqlTransformationException("Category without version: "+catName);
			String versionInfo = catName.substring(catName.lastIndexOf("__v")+2);
			String catNameWithoutVersion = catName.substring(0,catName.lastIndexOf("__v"));
			int newVersion;
			if(versionInfo.matches("v[0-9]{1,}"))
				newVersion = Integer.parseInt(versionInfo.substring(1));
			else
				continue;
			if(newVersion < dbTools.dbGetLastVersion(cat))
				throw new OwlToSqlTransformationException("Attempt to export outdated version of category: "+cat);
			int oldVersion = newVersion-1;
			String catNamePreviousVersion = catNameWithoutVersion+"__v"+oldVersion;
			if(newVersion > 1)
				listOfDependentCategories.addAll(this.deleteOldVersionsOfTheSameCategory(this.getDependencies(activeOntology.getOntologyID().getOntologyIRI()+"#"+catNamePreviousVersion)));
			
			log.info("listOfDependentCategories:"+listOfDependentCategories);
			for(String depCatName : listOfDependentCategories)
			{
//				OWLClass dependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatName));
				OWLClass dependentOWLClass;
//				String[] s = depCatName.split("__v");
//				log.info("depCatName:"+depCatName);
				String depCatNameWihoutVersion = depCatName.substring(0, depCatName.lastIndexOf("__v"));
				int version = Integer.parseInt(depCatName.substring(depCatName.lastIndexOf("__v")+3));
				OWLClass newDependentOWLClass;
				int c = 0;
				do
				{
					String depCatCurrentName = depCatNameWihoutVersion + "__v" + (version + c);
					dependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatCurrentName));
					c++;
					String depCatNewName = depCatNameWihoutVersion + "__v" + (version + c);
					newDependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatNewName));
					
				}
				while(dbTools.dbChceckIfCategoryAlreadyExported(newDependentOWLClass));
				String newDef = getCategoryAxiom(dependentOWLClass).replaceAll(catNamePreviousVersion, catName);
				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLEquivalentClassesAxiom(newDependentOWLClass, dlQueryParser.parseClassExpression(newDef))));
				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLSubClassOfAxiom(newDependentOWLClass, dlQueryParser.parseClassExpression(newDef.split(" ")[0]))));
	    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(newDependentOWLClass.getIRI(), getOWLDataFactory().getOWLAnnotation(getOWLDataFactory().getRDFSComment(), getOWLDataFactory().getOWLLiteral("This version was created autmatically on "+new java.util.Date()+".")))));
	    		exportNewCategory(newDependentOWLClass);
			}
			
		}
		
	}


	private ArrayList<String> deleteOldVersionsOfTheSameCategory(ArrayList<String> dependencies) throws OwlToSqlTransformationException 
	{
		HashMap<String, Integer> highestVersions = new HashMap<String, Integer>();
		for (String cat : dependencies)
		{
			if(!cat.contains("__v"))
				throw new OwlToSqlTransformationException("Category without version: "+cat);
			String catName = cat.substring(0, cat.lastIndexOf("__v"));
			int catVer = Integer.parseInt(cat.substring(cat.lastIndexOf("__v")+3));
			if(!highestVersions.containsKey(catName))
				highestVersions.put(catName, Integer.valueOf(catVer));
			else
			{
				int version = highestVersions.get(catName);
				if(version < catVer)
				{
					highestVersions.remove(catName);
					highestVersions.put(catName, Integer.valueOf(catVer));
				}
			}
		}
		
		ArrayList<String> l = new ArrayList<String>();
		for(String k : highestVersions.keySet())
			l.add(k + "__v" + highestVersions.get(k));
		
		return l;
	}

	private String getCategoryAxiom(OWLClass depCat) throws OwlToSqlTransformationException 
	{
    	Set<OWLClassExpression> eces = depCat.getEquivalentClasses(activeOntology);
    	if(eces.size() > 1)
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: more than one definition of category: "+depCat);
    	else if(eces.size() == 0)
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: no definitions of category: "+depCat);

    	String r = null;
    	for(OWLClassExpression ce : eces)
    	{
    		r = renderer.render(ce);
    	}
		return r;
	}
	
	private ArrayList<String> getDependencies(String categoryName) throws SQLException, OwlToSqlTransformationException 
	{
		log.info("Chceking dependecies for: "+categoryName);
		ArrayList<String> listOfAllDependentCategories = new ArrayList<String>();
		Long id = dbTools.dbGetCategoryId(getOWLDataFactory().getOWLClass(IRI.create(categoryName)));
		if(id != null)
		{
			listOfAllDependentCategories = dbTools.dbGetDependentCategories(id);
//			ArrayList<String> listOfDirectlyDependentCategories = dbTools.dbGetDependentCategories(id);
			
//			for(String dependentCategoryName : listOfDirectlyDependentCategories)
//			{
//				listOfAllDependentCategories.addAll(this.getDependencies(activeOntology.getOntologyID().getOntologyIRI()+"#"+dependentCategoryName)); 
//			}
		}
		else
			throw new OwlToSqlTransformationException("Unable to determine category id of: "+categoryName);
		
		return listOfAllDependentCategories;
		
	}

    private void initReasoner() throws OwlToSqlTransformationException 
    {
    	OWLReasonerManager reasonerManager = getOWLModelManager().getOWLReasonerManager();
		ReasonerUtilities.warnUserIfReasonerIsNotConfigured(getOWLWorkspace(), reasonerManager);
		if(reasonerManager.getReasonerStatus() != ReasonerStatus.INITIALIZED)
			throw new OwlToSqlTransformationException("No reasoner has been initialized!");
        reasoner = reasonerManager.getCurrentReasoner();
        reasoner.precomputeInferences(new InferenceType[0]);
	}

	private void exportHierarchy() throws SQLException, OwlToSqlTransformationException, OWLOntologyRenameException, ParserException
    {
		this.listOfSuccesfullyTransformedCategories.clear();
    	Set<OWLClass> classesToTranslate = reasoner.getSubClasses(selectedClass, false).getFlattened();
//	    classesToTranslate.add(lastSelectedClass);
	    for (OWLClass classToTranslate : classesToTranslate) 
	    {
	    	if(!classToTranslate.isOWLNothing())
	    	{
	    		if(dbTools.dbChceckIfCategoryAlreadyExported(classToTranslate))
	    			log.info("Category already exported: "+renderer.render(classToTranslate));
	    		else 
	    			this.exportCategory(classToTranslate);
	    	}
	    }
	}
    
	private void exportAllNewCategories() throws Exception 
    {
		this.listOfSuccesfullyTransformedCategories.clear();
    	Set<OWLClass> socls = this.activeOntology.getClassesInSignature(false);
    	for(OWLClass cls: socls)
    	{
        	if(!cls.isOWLNothing() && this.checkIfClassificationCategory(cls))
        	{
        		if(!this.dbTools.dbChceckIfCategoryAlreadyExported(cls))
        			this.exportCategory(cls);
        		else
        			log.info("Category "+cls+" already exported.");
        	}
    	}
	}
	
	private Long exportNewCategory(OWLClass categoryToExport) throws OwlToSqlTransformationException
	{
		listOfSuccesfullyTransformedCategories.clear();
		return exportCategory(categoryToExport);
	}

	
	private Long exportCategory(OWLClass categoryToExport) throws OwlToSqlTransformationException 
	{
    	if(categoryToExport.isOWLNothing())//owl:Nothing is a subclass of every OWL class
    		throw new OwlToSqlTransformationException("Unable to transform owl:Nothing!");
    	
    	if(!checkIfClassificationCategory(categoryToExport))
			throw new OwlToSqlTransformationException("OWL class "+categoryToExport+" is not a valid classification category!");
    	
    	if(reasoner == null)
    		throw new OwlToSqlTransformationException("No reasoner!");
    	
    	if(this.versionChceckingMode )
    		this.checkVersion(categoryToExport);
    	
    	log.info("Initiating transformation of the following OWL class: "+categoryToExport);
    	
    	if(!reasoner.isSatisfiable(categoryToExport))
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: unsatisfiable class: "+categoryToExport);
    	}
    	
    	Set<OWLClassExpression> eces = categoryToExport.getEquivalentClasses(activeOntology);
    	if(eces.size()>1)
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: more than one definition of category: "+categoryToExport);
    	}
    	else if(eces.size()==0)
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: no definition for category: "+categoryToExport);
    	}
    	
		Long newId = null;
    	for(OWLClassExpression ece : eces)
    	{
    		String basicSql;
    		Integer backwardValidity = null;
    		Integer forwardValidity = null;
    		
    		Set<OWLClass> categoriesInDefinition = ece.getClassesInSignature();
    		String expressionToTransform = renderer.render(ece);
    		if(ManchesterOWLSyntaxEditorParser.SOME.equals("koniecznie"))
    			expressionToTransform = translatePLtoENG(expressionToTransform);
    		expressionToTransform = EventRendering.transformRendering(expressionToTransform);//this makes expression available for parsing of indented temporal dependencies
    		
    		String selectClause;
//			if((expressionToTransform.contains(" and ") || expressionToTransform.contains(" or ")) && (expressionToTransform.contains(" some ") || expressionToTransform.contains(" value ")))
			if(expressionToTransform.contains("occurs_"))
    		{//temporal category
    			try //determine temporal validity
    			{
    					TemporalExpressionAnalyzer a = new TemporalExpressionAnalyzer(expressionToTransform);
    					backwardValidity = a.determineBackwardValidityOfAnExpresion();
    					forwardValidity = a.determineForwardValidityOfAnExpresion();
    			}
    			catch (Exception e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to analyze following definition: "+ expressionToTransform, e1);
    			}
    			
    			try 
    			{
    				basicSql = temporalCategoryTransformer.transformOWLClassExpression(expressionToTransform);
    				log.info("Transformation succesful!");
        			selectClause = "SELECT pPROCESS_ID, ID ";
    				if(lfConfig.isWriteReport())
    					listOfSuccesfullyTransformedCategories.add(categoryToExport);
    			} 
    			catch (OwlToSqlTransformationException e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to transform following definition: "+ expressionToTransform, e1);

    			}
    			
    			if(backwardValidity != null)
    			{
    				for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    				{
    					if(anAxiom.getProperty().equals(backwardValidityAP))
    						activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    				}
    				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(backwardValidityAP, getOWLDataFactory().getOWLLiteral(backwardValidity)))));
    			}
    			if(forwardValidity != null)
    			{
    				for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    				{
    					if(anAxiom.getProperty().equals(forwardValidityAP))
    						activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    				}
    				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(forwardValidityAP, getOWLDataFactory().getOWLLiteral(forwardValidity)))));
    			}
    			
    		}		
    		else if((expressionToTransform.contains(" and ") || expressionToTransform.contains(" or ")) && !expressionToTransform.contains(" some ") && !expressionToTransform.contains(" value "))
    		{//compound category
    			try 
    			{
    				basicSql = compoundCategoryTransformer.transformOWLClassExpression(expressionToTransform);
    				log.info("Transformation succesful!");
    				selectClause = "SELECT pPROCESS_ID, EVENT_ID ";
    				if(lfConfig.isWriteReport())
    					listOfSuccesfullyTransformedCategories.add(categoryToExport);
    			} 
    			catch (OwlToSqlTransformationException e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to transform following definition: "+expressionToTransform, e1);
    			}
    			
    		}
    		else
    		{
	    		throw new OwlToSqlTransformationException("Unable to transform category - unsupported definition: "+expressionToTransform);
    		}
    		
    		for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    		{
    			if(anAxiom.getProperty().equals(sqlSelectAP))
    				activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    		}
    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(sqlSelectAP, getOWLDataFactory().getOWLLiteral(basicSql)))));
    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(getOWLDataFactory().getRDFSComment(), getOWLDataFactory().getOWLLiteral("An SQL script was generated by EventsToSQLP4Transformer on "+new java.util.Date()+".")))));
    		
    		try 
    		{
    			log.info("Exporting to database...");
				newId = Long.valueOf(this.dbTools.dbGetSequenceNextValue(lfConfig.getDbCategorySequenceName()));
				String newProcName = "P"+newId;
				String categoryType = expressionToTransform.split(" ")[0];
				Long categoryTypeId = getCategoryTypeID(getCategoryTypeOWLClass(categoryType, ece));
				String resultsTable = getResultsTableName(categoryType);
				this.dbTools.dbCreateClassificationProcedure(newProcName, basicSql.replaceFirst("SELECT \\* ", selectClause), resultsTable);
				this.dbTools.dbAddCategory(categoryToExport, newProcName, categoryTypeId, newId, expressionToTransform);
				this.determineCategoryDependency(categoryToExport, newId, categoriesInDefinition);
				if(versionChceckingMode)
        			this.exportNewVersionsOfRelatedCategories();
			}
    		catch (Exception e) 
    		{
    			try {
					dbTools.dbRollback();
				} catch (SQLException e1) {
					log.error(e1);
					throw new OwlToSqlTransformationException(e.getMessage());
				}
    			log.error("Unable to export category... ", e);
	    		throw new OwlToSqlTransformationException("Unable to export category... ", e);
    			
			}
    	}
//    	try {
//			dbTools.dbCommit();
//		} catch (SQLException e1) {
//			log.error(e1);
//			throw new OwlToSqlTransformationException(e1.getMessage());
//		}
    	return newId;
	}

	private String getResultsTableName(String type) throws Exception 
	{
		String key = "DbResultsTable-"+type;
		String r = dbConfig.getProperty(key);
		if(r == null)
			throw new Exception("Unable to determine results table for type: "+type+"; param: "+key);
		else
			return r;
	}
	
	private String getResultsTableName(OWLClass category) throws Exception 
	{
		String key = "DbResultsTable-"+getCategoryType(category);
		String r = dbConfig.getProperty(key);
		if(r == null)
			throw new Exception("Unable to determine results table for category: "+category+"; param: "+key);
		else
			return r;
	}

	private void determineCategoryDependency(OWLClass classToTranslate,	long newCategoryId, Set<OWLClass> categoriesInDefinition) throws Exception 
	{
//		Set<OWLClass> categoriesInvolved = new HashSet<OWLClass>();
		log.info(categoriesInDefinition);
		for(OWLClass category : categoriesInDefinition)
		{
//			if(categoriesInvolved.contains(category))
//			categoriesInvolved.add(category);
			
			OWLClassExpression def = null;
			Set<OWLClassExpression> eces = category.getEquivalentClasses(activeOntology);
	    	int i = 0;
	    	for(OWLClassExpression ece : eces)
	    	{
	    		i++;
	    		if(i>1)
	    			throw new OwlToSqlTransformationException("More than 1 definitions for: "+ category);
	    		
	    		def = ece;
	    	}
			
			if(def != null && checkIfClassificationCategory(category))
			{
				log.info("Analyzing: "+category);
				alreadyCheckedCombinations = new HashSet<String>();
				this.checkIfContainsCycle(classToTranslate, def);
				Long preceedingCategoryId = dbTools.dbGetCategoryId(category);
				if(preceedingCategoryId != null)
					log.info("Category "+category + " has been already exported.");
				else
				{
					log.info("Category "+category + " has to be exported because of dependency relationship.");
					preceedingCategoryId = this.exportCategory(category);
				}
				
				if(preceedingCategoryId != null)
				{
					dbTools.dbAddCategoryDependency(newCategoryId, preceedingCategoryId);
					log.info("Dependency added.");
				}
				else
					log.warn("Unable to obtain id for: "+category);
			}
		}
	}

	private boolean checkIfClassificationCategory(OWLClass category) 
	{
		if(checkIfBaseCategory(category))
			return false;
			
		for(OWLClassExpression scls : category.getSuperClasses(activeOntology))
		{
			if(!scls.isAnonymous())
			{
				if(checkIfBaseCategory(scls.asOWLClass()))
					return true;
			}
		}
		
		for(OWLClass scls : reasoner.getSuperClasses(category, false).getFlattened())
		{
			if(!scls.isAnonymous())
			{
				if(checkIfBaseCategory(scls.asOWLClass()))
					return true;
			}
		}
		
		return false;
	}
	
	private boolean checkIfBaseCategory(OWLClass category) 
	{
		return checkIfContainsAnnotation(category, baseCategoryAP, activeOntology);
	}


//	private boolean checkIfClassificationCategory(OWLClass category, OWLClassExpression def) 
//	{
//		
//		if(renderer.render(def).contains("occurs_"))
//			return true; 
//		else
//		{
//			for(OWLAnnotationAssertionAxiom anAxiom : category.getAnnotationAssertionAxioms(activeOntology))
//			{
//				if(anAxiom.getProperty().equals(baseCategoryAP))
//					return true;
//			}
//		}
//		return false;
//	}

	private void checkIfContainsCycle(OWLClass searchedCategory, OWLClassExpression def) throws OwlToSqlTransformationException 
	{
		String s = searchedCategory + ", "+renderer.render(def);
		log.info("checkIfContainsCycle: "+s);
		if(alreadyCheckedCombinations.contains(s))
		{
			log.info("Combination already checked!");
			return;
		}
		else
			alreadyCheckedCombinations.add(s);
		Set<OWLClass> categoriesInDefinition = def.getClassesInSignature();
		for(OWLClass ctFromDef : categoriesInDefinition)
		{
			if(searchedCategory.equals(ctFromDef))
    			throw new OwlToSqlTransformationException("Cycle detected in definition of "+ ctFromDef + "! Inapropriate reference to: "+searchedCategory);
			else
			{
				OWLClassExpression nextDef = null;
				Set<OWLClassExpression> eces = ctFromDef.getEquivalentClasses(activeOntology);
		    	int i = 0;
		    	for(OWLClassExpression ece : eces)
		    	{
		    		i++;
		    		if(i>1)
		    		{
		    			nextDef = null;
		    			continue;
		    		}
		    		
		    		nextDef = ece;
		    	}
		    	
		    	if(nextDef != null && checkIfClassificationCategory(ctFromDef))
		    		checkIfContainsCycle(searchedCategory, nextDef);
			}
		}	
	}
	
	private void checkVersion(OWLClass categoryToExport) throws OwlToSqlTransformationException
	{
	// TODO imlementation
		
		
	}

    
	private String getCategoryType(OWLClass categoryToExport) throws Exception 
	{
		Set<OWLClassExpression> eces = categoryToExport.getEquivalentClasses(activeOntology);
    	if(eces.size()>1)
    		throw new Exception("Too many definitions - unable to export category: "+categoryToExport);
    	String s = null;
    	for(OWLClassExpression ece : eces)
    	{
    		s = EventRendering.transformRendering(renderer.render(ece)).split(" ")[0];
//    		s = ece.toString().split(" ")[0];
    	}
    	return s;
	}
	
	private long getCategoryTypeID(OWLClass owlClass) throws SQLException
	{
		Long id = dbTools.dbGetCategoryTypeId(owlClass);
		if(id == null)
		{
			id = Long.valueOf(this.dbTools.dbGetSequenceNextValue(lfConfig.getDbCategoryTypeSequenceName()));
			this.dbTools.dbAddCategoryType(owlClass, id);
		}
		
		return id;
	}

	private OWLClass getCategoryTypeOWLClass(String categoryTypeIRIFragment, OWLClassExpression ece) throws OwlToSqlTransformationException 
	{
		OWLClass result = null;
		for(OWLClass c : ece.getClassesInSignature())
		{
			if(renderer.render(c).equals(categoryTypeIRIFragment))
			{
				if(result == null)
					result = c;
				else
					throw new OwlToSqlTransformationException("Duplicate OWL classes with IRI fragment: "+categoryTypeIRIFragment);
			}
		}
		return result;
	}
	

	private void initClassification(OWLClass category) throws Exception 
    {
		this.dbTools.dbInitClassification(category, getResultsTableName(category), getSrcTableName(category));
		this.dbTools.dbCommit();
	}



	private String getSrcTableName(OWLClass category) throws Exception
	{
		String srcTableName = this.lfConfig.getDomainClassMapping(getCategoryType(category)).getTableName();
    	if(srcTableName == null)
    		throw new Exception("Unable to determine source table for "+selectedClass);
    	else
    		return srcTableName;
	}

	// called automatically when the global selection changes
    protected OWLClass updateView(OWLClass selectedClass) 
    {
    	this.selectedClass = selectedClass;
        if (selectedClass != null && dbTools != null)
        {
        	ArrayList<ClassificationProcess> cProcList = new ArrayList<ClassificationProcess>();
        	ClassificationResults clRes = null;
            try 
            {
            	cProcList = dbTools.dbGetCategoryData(selectedClass.getIRI().getFragment());
            	String srcTableName = this.lfConfig.getDomainClassMapping(getCategoryType(selectedClass)).getTableName();
            	if(srcTableName == null)
            		throw new Exception("Unable to determine source table for "+selectedClass);
            	String resultsTableName = getResultsTableName(this.selectedClass);
            	if(resultsTableName == null)
            		throw new Exception("Unable to determine results table for "+selectedClass);
            	if(cProcList.size()>0)
            		clRes = this.dbTools.dbGetResults(resultsTableName, cProcList.get(cProcList.size()-1).processId.longValue(), srcTableName, -1);
			}
            catch (Exception e) 
            {
                String errInfo = "Unable to retrieve data about "+ selectedClass;
                log.error(errInfo, e);
            }
            render(cProcList);
            if(clRes != null)
            	renderResults(clRes);
            
            if(clTable.getRowCount() > 0)
            {
            	exportSelectedCategory.setEnabled(false);
            }
            else
            {
            	resultsTable.setModel(new DefaultTableModel());//clearing whole table
            	exportSelectedCategory.setEnabled(true);
				try 
				{
					if(this.dbTools.dbChceckIfCategoryAlreadyExported(this.selectedClass))
						this.exportSelectedCategory.setEnabled(false);
//					else
//						JOptionPane.showMessageDialog(this,
//								"Selected category has not been exported yet.\nUse 'Export selected category' button to export this category.",
//								"Category viewer",
//								JOptionPane.INFORMATION_MESSAGE);
				}
				catch (SQLException e) 
				{
					log.error(e);
				}
            }
        }
        return selectedClass;
    }


	private void render(ArrayList<ClassificationProcess> cProcList) 
    {
		int colmnsCount = ClassificationProcess.numberOfFieldsToDisplay;
		DefaultTableModel model = new DefaultTableModel(new String[]{"ID", "STATUS", "ENTRY DATE", "START DATE", "END DATE", "RESULTS NUMBER", "RESULTS TABLE", "INFO"}, 0)
		{
			 /**
			 * 
			 */
			private static final long serialVersionUID = -2992689192047455264L;

			@Override
 		    public boolean isCellEditable(int row, int column) 
			{
 		        return false;
 		    }
		};
		
		for(int i=0;i<cProcList.size();i++)
		{
			Object[] row = new Object[colmnsCount];
			int columnNumber = 0;
			row[columnNumber++] = cProcList.get(i).processId;
			row[columnNumber++] = cProcList.get(i).status;
			row[columnNumber++] = cProcList.get(i).initDate;
			row[columnNumber++] = cProcList.get(i).startDate;
			row[columnNumber++] = cProcList.get(i).endDate;
//			row[columnNumber++] = cProcList.get(i).duration;
			if(cProcList.get(i).endDate != null)
				row[columnNumber++] = cProcList.get(i).resultsCount;
			else
				row[columnNumber++] = null;
			row[columnNumber++] = cProcList.get(i).resultsTable;
			row[columnNumber++] = cProcList.get(i).info;
			model.addRow(row);
		}
		clTable.setModel(model);
    }
	
	private void renderResults(ClassificationResults clRes) 
    {
		int resultsCount = clRes.resList.size();
		int colmnsCount = clRes.columns.size();
		DefaultTableModel model = new DefaultTableModel(clRes.columns.toArray(), 0)
		{
			/**
			 * 
			 */
			private static final long serialVersionUID = -102444310262293521L;

			@Override
 		    public boolean isCellEditable(int row, int column) 
			{
 		        return false;
 		    }
		};
		
		for(int i=0;i<resultsCount;i++)
		{
			ArrayList<String> rowData = clRes.resList.get(i);
			Object[] row = new Object[colmnsCount];
			int columnNumber = 0;
			for(int c=0;c<rowData.size();c++)
			{
				row[columnNumber++] = rowData.get(c);
			}
			model.addRow(row);
		}
		resultsTable.setModel(model);
		if(resultsCount < 100)
			this.showMoreResults.setEnabled(false);
		else
			this.showMoreResults.setEnabled(true);
    }

    public void disposeView() 
    {
		dbTools.dbDeactivateDbObjects();
	}
    
    class ClassificationProcess
    {
    	public static final int numberOfFieldsToDisplay = 8;
		java.util.Date startDate;
		java.util.Date initDate;
    	java.util.Date endDate;
//    	Long duration;
    	Long resultsCount;
    	Long processId;
    	String status;
    	String info;
    	String resultsTable;
    	
    }
    
    class ClassificationResults
    {
    	ArrayList<ArrayList<String>> resList = new ArrayList<ArrayList<String>>();
    	ArrayList<String> columns = new ArrayList<String>();
    }
    
    
    @SuppressWarnings("unused")
	private Connection getSimpleConnection(String connURL, String driverName)
    {
	    Connection result = null;
	    try 
	    {
	       Class.forName(driverName).newInstance();
	    }
	    catch (Exception e){
	       System.out.println("Check classpath. Cannot load db driver: " + driverName);
	       e.printStackTrace();
	    }

	    try
	    {
	      result = DriverManager.getConnection(connURL);
	    }
	    catch (SQLException e)
	    {
	    	System.out.println( "Driver loaded, but cannot connect to db: " + connURL);
		    e.printStackTrace();

	    }
	    return result;
	}
    
    
    public interface LinkedFactsDBInteractionDbTools
    {
    	public long dbGetSequenceNextValue(String seqName) throws SQLException;
		public void dbDeactivateDbObjects();
		public void dbAddCategory(OWLClass categoryToExport, String newProcName, long categoryTypeId, long id, String definition) throws SQLException;
		public ClassificationResults dbGetResults(String resultsTable, long processId, String srcTableName, int fetchGreaterThan) throws SQLException;
		public void dbInitClassification(OWLClass category, String resultTable, String srcTable) throws SQLException;
		public boolean dbChceckIfCategoryAlreadyExported(OWLClass cls) throws SQLException;
		public void dbCreateClassificationProcedure(String newProcName,	String sqlCat, String resultTable) throws SQLException;
	    public ArrayList<ClassificationProcess> dbGetCategoryData(String catIRI) throws SQLException;

	    public Long dbGetCategoryId(OWLClass cls) throws SQLException;
		public Long dbGetCategoryTypeId(OWLClass cls) throws SQLException;
		public void dbAddCategoryType(OWLClass categoryToExport, Long id) throws SQLException;
		public void dbAddCategoryDependency(Long newCategoryId, Long preceedingCategoryId) throws SQLException;
		public void dbCommit() throws SQLException;
		public void dbRollback() throws SQLException;
		public ArrayList<String> dbGetDependentCategories(Long categoryId) throws SQLException;
		public int dbGetLastVersion(OWLClass cat) throws SQLException;
		
//	    public ClassificationResults dbGetResults(String catName, int fetchGreaterThan) throws SQLException;

    }

    class LinkedFactsDBInteractionPostgresDbTools extends LinkedFactsDBInteractionCommonDbTools
    {

		public LinkedFactsDBInteractionPostgresDbTools(Connection conn) throws SQLException 
		{
			super(conn);
		}
		
		@Override
		public long dbGetSequenceNextValue(String seqName) throws SQLException 
		{
			Statement s = null;
			ResultSet rs = null;
			String sql = "SELECT nextval('"+dbAppSchema+"."+seqName+"')";
			try
			{
				log.info("Creating statement: "+ sql);
				s = conn.createStatement();
				rs = s.executeQuery(sql);
				log.info("dbGetSequenceNextValue completed!");
				if(rs.next())
					return rs.getLong(1);
				else
					throw new SQLException("Unable to use sequence "+seqName);
				
			}
			catch (SQLException e)
			{
				log.error(e);
				throw e;
			}
		}

		
		
		@Override
		public void dbCreateClassificationProcedure(String newProcName, String sqlCat, String resultTable) throws SQLException 
		{
			//TODO: align it to DB2 version
			Statement s = null;
			StringBuffer sb = new StringBuffer();
			sb.append("CREATE OR REPLACE FUNCTION "+dbAppSchema+"."+newProcName+" "); 
			sb.append("( pPROCESS_ID INTEGER) "); 
			sb.append("RETURNS void AS $$ "); 
			sb.append("DECLARE vRESULTS_COUNT INTEGER; "); 
			sb.append("DECLARE vPROCESS_COUNT INT; "); 
			sb.append("BEGIN "); 
			sb.append("SELECT COUNT(*) INTO vPROCESS_COUNT FROM "+lfConfig.getDbAppSchema()+".PROCESS WHERE START_TIME IS NOT NULL AND ID = pPROCESS_ID; "); 
			sb.append("IF vPROCESS_COUNT = 0 THEN "); 
				sb.append("UPDATE "+dbAppSchema+".PROCESS SET STATUS = 1, START_TIME = timeofday()::timestamp WHERE ID = pPROCESS_ID; "); 
				sb.append("INSERT INTO "+dbAppSchema+"."+resultTable+" "); 
				sb.append(sqlCat + "; "); 
	//			sb.append(sqlCat.substring(1, sqlCat.length()-1).replaceFirst("SELECT \\* ", "SELECT pPROCESS_ID, S1L1.ID ")+"; "); //ommiting double quotes
				sb.append("GET DIAGNOSTICS vRESULTS_COUNT = ROW_COUNT; ");
				sb.append("UPDATE "+dbAppSchema+".PROCESS SET STATUS = 2, RESULTS_COUNT = vRESULTS_COUNT, END_TIME = timeofday()::timestamp WHERE ID = pPROCESS_ID; "); 
			sb.append("END IF; ");
			sb.append("RETURN; ");
			sb.append("END; ");
			sb.append(" $$ LANGUAGE plpgsql;");
			
			String sql = sb.toString();
			log.info(sql);
			try {
				s = conn.createStatement();
				s.executeUpdate(sql);
			} catch (SQLException e) {
				e.printStackTrace();
				log.error(e);
				throw e;
			}
			
		}
    	
    }
    
    class LinkedFactsDBInteractionDB2Tools extends LinkedFactsDBInteractionCommonDbTools
    {

		
		public LinkedFactsDBInteractionDB2Tools(Connection conn) throws SQLException 
		{
			super(conn);
		}

		@Override
		public long dbGetSequenceNextValue(String seqName) throws SQLException 
		{
			Statement s = null;
			ResultSet rs = null;
			try
			{
				String sql = "SELECT NEXT VALUE FOR "+dbAppSchema+"."+seqName+" AS NEXTID FROM SQLTOOLS.DUAL FOR FETCH ONLY";
				log.info(sql);
				s = conn.createStatement();
				rs = s.executeQuery(sql);
				if(rs.next())
					return rs.getLong(1);
				else
					throw new SQLException("Unable to use sequence "+seqName);
				
			}
			catch (SQLException e)
			{
				e.printStackTrace();
				log.error(e);
				throw e;
			}
		}
		
		@Override
		public void dbCreateClassificationProcedure(String newProcName, String sqlCat, String resultTable) throws SQLException 
		{
			Statement s = null;
			StringBuffer sb = new StringBuffer();
			sb.append("CREATE PROCEDURE "+lfConfig.getDbAppSchema()+"."+newProcName+" "); 
			sb.append("( IN pPROCESS_ID INT) "); 
			sb.append("LANGUAGE SQL "); 
			sb.append("MODIFIES SQL DATA "); 
			sb.append("CALLED ON NULL INPUT SET OPTION ALWBLK = *ALLREAD , ALWCPYDTA = *OPTIMIZE , COMMIT = *NONE "); //*NONE has to be stated here in beacause *CHG is the default
			sb.append("BEGIN "); 
			sb.append("DECLARE vRESULTS_COUNT INT; "); 
			sb.append("DECLARE vPROCESS_COUNT INT; "); 
			sb.append("SELECT COUNT(*) INTO vPROCESS_COUNT FROM "+lfConfig.getDbAppSchema()+".PROCESS WHERE START_TIME IS NOT NULL AND ID = pPROCESS_ID; "); 
			sb.append("IF vPROCESS_COUNT = 0 THEN "); 
				sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 1, START_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
				sb.append("INSERT INTO "+lfConfig.getDbAppSchema()+"."+resultTable+" "); 
				sb.append(sqlCat + "; "); 
				sb.append("GET DIAGNOSTICS vRESULTS_COUNT = ROW_COUNT; ");
				sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 2, RESULTS_COUNT = vRESULTS_COUNT, END_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
			sb.append("END IF; ");
			sb.append("END ");
			String sql = sb.toString();
			log.info(sql);
			try {
				s = conn.createStatement();
				s.executeUpdate(sql);
			} catch (SQLException e) {
				e.printStackTrace();
				log.error(e);
				throw e;
			}
			
		}
    	
    }
    
    abstract class LinkedFactsDBInteractionCommonDbTools implements LinkedFactsDBInteractionDbTools
    {
    	
        protected PreparedStatement psAddCategory;
        protected PreparedStatement psCheckIfAlreadyExported;
        protected PreparedStatement psGetCategoryData;
//      protected PreparedStatement psGetProcessData;
//      protected PreparedStatement psGetResults;
	    protected PreparedStatement psAddCategoryType;
	    protected PreparedStatement psGetCategoryId;
	    protected PreparedStatement psGetCategoryTypeId;
	    protected PreparedStatement psAddDependency;
	    protected PreparedStatement psGetDependentCategories;
	    protected PreparedStatement psGetLastVersion;
    	
	    protected Connection conn;

		public LinkedFactsDBInteractionCommonDbTools(Connection conn) throws SQLException
    	{
			this.conn = conn;
    		psAddCategory = conn.prepareStatement("INSERT INTO "+dbAppSchema+".CATEGORY(IRI, NAME, PROC_NAME, TYPE_ID, ENTRY_TIME, ID, DEFINITION) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)");
    		psCheckIfAlreadyExported = conn.prepareStatement("SELECT 1 FROM "+dbAppSchema+".CATEGORY WHERE NAME = ? FOR READ ONLY ");
    		psGetCategoryData = conn.prepareStatement("SELECT P.ID AS PROCESS_ID, P.START_TIME, P.END_TIME, P.RESULTS_COUNT, CASE P.STATUS WHEN '0' THEN 'WAITING' WHEN '1' THEN 'RUNNING' WHEN '2' THEN 'COMPLETED' WHEN '3' THEN 'ERROR' END AS STATUS, P.INFO, P.RES_TABLE, P.INIT_TIME FROM "+dbAppSchema+".CATEGORY C JOIN "+dbAppSchema+".PROCESS P ON P.CATEGORY_ID = C.ID WHERE C.NAME = ? FOR READ ONLY");
    		psAddCategoryType = conn.prepareStatement("INSERT INTO "+lfConfig.getDbAppSchema()+".CAT_TYPE(IRI, NAME, ID) VALUES (?, ?, ?)");
    		psGetCategoryId = conn.prepareStatement("SELECT ID FROM "+lfConfig.getDbAppSchema()+".CATEGORY WHERE NAME = ? FOR READ ONLY ");
    		psGetCategoryTypeId = conn.prepareStatement("SELECT ID FROM "+lfConfig.getDbAppSchema()+".CAT_TYPE WHERE NAME = ? FOR READ ONLY ");
    		psAddDependency = conn.prepareStatement("INSERT INTO "+lfConfig.getDbAppSchema()+".DEPENDENCY(DEPCAT_ID, PRECAT_ID) VALUES (?, ?)");
    		psGetDependentCategories = conn.prepareStatement("SELECT C.NAME FROM "+lfConfig.getDbAppSchema()+".DEPENDENCY D JOIN "+lfConfig.getDbAppSchema()+".CATEGORY C ON C.ID=D.DEPCAT_ID WHERE PRECAT_ID = ? FOR READ ONLY ");
    		psGetLastVersion = conn.prepareStatement("SELECT C.NAME FROM "+dbAppSchema+".CATEGORY C WHERE NAME LIKE ? ORDER BY 1 DESC FOR READ ONLY ");
		}
		
		public void dbCommit() throws SQLException
		{
			log.warn("DB COMMIT");
			conn.commit();
		}

		public void dbRollback() throws SQLException
		{
			log.warn("DB ROLLBACK");
			conn.rollback();
		}
		
		public void dbDeactivateDbObjects()
		{
			try 
			{
				if(psGetCategoryData != null)
					psGetCategoryData.close();
				if(psAddCategory != null)
					psAddCategory.close();
				if(psCheckIfAlreadyExported != null)
					psCheckIfAlreadyExported.close();
				if(psAddCategoryType != null)
					psAddCategoryType.close();
				if(psGetCategoryData != null)
					psGetCategoryData.close();
				if(psGetCategoryId != null)
					psGetCategoryId.close();
				if(psGetCategoryTypeId != null)
					psGetCategoryTypeId.close();
				if(psAddDependency != null)
					psAddDependency.close();
				if(conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				log.error("SQL error while closing DB objects.");
			}
		
		}

	    public ArrayList<ClassificationProcess> dbGetCategoryData(String catName) throws SQLException
	    {
	    	ArrayList<ClassificationProcess> resList = new ArrayList<ClassificationProcess>();
	    	ResultSet rs = null;
//	    	SimpleDateFormat fmt = new SimpleDateFormat(DEFAULT_TIMESTAMP_FORMAT);
	        try 
	        {
	            psGetCategoryData.setString(1, catName);
	            rs = psGetCategoryData.executeQuery();

	            while(rs.next())
	            {
	            	ClassificationProcess cProcess = new ClassificationProcess();
	            	cProcess.processId = rs.getLong(1);
//	            	cProcess.startDate = fmt.parse(rs.getString(2));
//	            	cProcess.endDate = fmt.parse(rs.getString(3));
	            	cProcess.startDate = parseTimestamp(rs.getTimestamp(2));
	            	cProcess.endDate = parseTimestamp(rs.getTimestamp(3));
//	            	cProcess.duration = rs.getLong(4);
	            	cProcess.resultsCount = rs.getLong(4);
	            	cProcess.status = rs.getString(5);
	            	cProcess.info = rs.getString(6);
	            	cProcess.resultsTable = rs.getString(7);
	            	cProcess.initDate = parseTimestamp(rs.getTimestamp(8));
	            	resList.add(cProcess);
	            }
	            
	        } 
	        catch (Exception e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
	        return resList;
		}
	
		private Date parseTimestamp(Timestamp timestamp) 
		{
			if(timestamp != null)
				timestamp.setNanos(0);
			return timestamp;
		}

		public ClassificationResults dbGetResults(String resultsTable, long processId, String srcTableName, int fetchGreaterThan) throws SQLException
	    {
			String sql = "SELECT B.* FROM "+dbAppSchema+"."+resultsTable+" A JOIN "+srcTableName+" B ON A.EVENT_ID = B.ID WHERE PROCESS_ID = ? AND A.EVENT_ID  > ? FETCH FIRST 1000 ROWS ONLY FOR READ ONLY ";
	    	log.info("Result SQL: "+sql+"\nFetching greater than: "+fetchGreaterThan);
	    	
	    	ResultSet rs = null;
	    	ClassificationResults clRes = new ClassificationResults();
	        PreparedStatement ps = null;
			try 
	        {
	            ps  = conn.prepareStatement(sql);

	            ps.setLong(1, processId);
	        	ps.setInt(2, fetchGreaterThan);
	            
	        	rs = ps.executeQuery();
	            ResultSetMetaData m = rs.getMetaData();
	            int columnCount = m.getColumnCount();
	        	for(int i=1;i<=columnCount;i++)
	        		clRes.columns.add(m.getColumnName(i));
	           
	        	while(rs.next())
	            {
	            	ArrayList<String> row = new ArrayList<String>();
	            	
	            	for(int i=1;i<=columnCount;i++)
	            		row.add(rs.getString(i));

	            	clRes.resList.add(row);
	            }
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	            if(ps!=null)
	            	ps.close();
	        }
	        return clRes;
		}

		@Override
		public boolean dbChceckIfCategoryAlreadyExported(OWLClass cls) throws SQLException 
		{
	    	ResultSet rs = null;
	        try 
	        {
	        	psCheckIfAlreadyExported.setString(1, cls.getIRI().getFragment());
	            rs = psCheckIfAlreadyExported.executeQuery();
	            
	            log.info("dbChceckIfCategoryAlreadyExported: "+ cls.getIRI().getFragment());
	        	return rs.next();
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}

	  	public Long dbGetCategoryId(OWLClass cls) throws SQLException
    	{
	    	ResultSet rs = null;
	        try 
	        {
	        	psGetCategoryId.setString(1, cls.getIRI().getFragment());
	            rs = psGetCategoryId.executeQuery();
	            
	            log.info("psGetCategoryId: "+ cls.getIRI().getFragment());
	        	if(rs.next())
	        		return rs.getLong(1);
	        	else
	        		return null;
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}
    	
    	public Long dbGetCategoryTypeId(OWLClass cls) throws SQLException
    	{
    		ResultSet rs = null;
    		try 
    		{
    			psGetCategoryTypeId.setString(1, cls.getIRI().getFragment());
    			rs = psGetCategoryTypeId.executeQuery();
    			
    			log.info("psGetCategoryTypeId: "+ cls.getIRI().getFragment());
    			if(rs.next())
    				return rs.getLong(1);
    			else
    				return null;
    			
    		} 
    		catch (SQLException e) 
    		{
    			e.printStackTrace();
    			log.error(e);
    			throw e;
    		}
    		finally 
    		{
    			if(rs!=null)
    				rs.close();
    		}
    	}
		


		@Override
		public void dbAddCategory(OWLClass categoryToExport, String newProcName, long categoryTypeId, long id, String definition) throws SQLException 
		{
	        try 
	        {
	        	psAddCategory.setString(1, categoryToExport.getIRI().toString());
	        	psAddCategory.setString(2, categoryToExport.getIRI().getFragment());
	        	psAddCategory.setString(3, newProcName);
	        	psAddCategory.setLong(4, categoryTypeId);
	        	psAddCategory.setLong(5, id);
	        	psAddCategory.setString(6, definition);
	        	
	        	psAddCategory.execute();
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
		}
		
		@Override
		public void dbAddCategoryType(OWLClass categoryToExport, Long id) throws SQLException 
		{
			try 
			{
				psAddCategoryType.setString(1, categoryToExport.getIRI().toString());
				psAddCategoryType.setString(2, categoryToExport.getIRI().getFragment());
				psAddCategoryType.setLong(3, id);

				
				psAddCategoryType.execute();
			} 
			catch (SQLException e) 
			{
				e.printStackTrace();
				log.error(e);
				throw e;
			}
		}
		
		public void dbAddCategoryDependency(Long newCategoryId, Long preceedingCategoryId) throws SQLException
		{
			try 
	        {
	        	psAddDependency.setLong(1, newCategoryId);
	        	psAddDependency.setLong(2, preceedingCategoryId);
	        	
	        	psAddDependency.execute();
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	       }
		}


		@Override
		public void dbInitClassification(OWLClass category, String resultTable, String srcTable) throws SQLException 
		{
			PreparedStatement ps = null;
		    try 
	        {

		    	ps = conn.prepareStatement("INSERT INTO "+dbAppSchema+".PROCESS (CATEGORY_ID, STATUS, RES_TABLE, SRC_TABLE) SELECT ID, 0, '"+resultTable+"', '"+srcTable+"' FROM "+dbAppSchema+".CATEGORY C WHERE C.NAME = ? ");
		    	ps.setString(1, category.getIRI().getFragment());
	        	
		    	ps.execute();
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
		    finally
		    {
	    	   if(ps!=null)
	            	ps.close();
		    }
			
		}
		
		public ArrayList<String> dbGetDependentCategories(Long categoryId) throws SQLException
		{
			ResultSet rs = null;
			ArrayList<String> l = new ArrayList<String>();
	        try 
	        {
	        	log.info("psGetDependentCategories: "+ categoryId);
	        	psGetDependentCategories.setLong(1, categoryId);
	            rs = psGetDependentCategories.executeQuery();
	            
				while (rs.next())
	        		l.add(rs.getString(1));
				
				return l;
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}
		
		public int dbGetLastVersion(OWLClass cls) throws SQLException
		{
	 		ResultSet rs = null;
    		try 
    		{
    			log.info(cls.getIRI().getFragment().substring(0, cls.getIRI().getFragment().lastIndexOf("__v")+3).concat("%"));
    			psGetLastVersion.setString(1, cls.getIRI().getFragment().substring(0, cls.getIRI().getFragment().lastIndexOf("__v")+3).concat("%"));
    			rs = psGetLastVersion.executeQuery();
    			
    			log.info("psGetLastVersion: "+ cls.getIRI().getFragment());
    			if(rs.next())
    			{
    				String s = rs.getString(1);
    				if(s.contains("__v")) 
    				{
    					int v = Integer.parseInt(s.substring(s.lastIndexOf("__v")+3));
    					log.info(v);
    					return v;
    				}
    				else
    					return -1;
    			}
    			else
    				return -1;
    			
    		} 
    		catch (SQLException e) 
    		{
    			e.printStackTrace();
    			log.error(e);
    			throw e;
    		}
    		finally 
    		{
    			if(rs!=null)
    				rs.close();
    		}
		}

    }
    
    /*
	 * Some common methods. Consider moving them to a separate tools class.
	 * 
	 */
    protected static String showPasswordPanel(String message)
	{
		JPasswordField pf = new JPasswordField();
		int okCxl = JOptionPane.showConfirmDialog(null, pf, message, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		
		if (okCxl == JOptionPane.OK_OPTION) 
			return new String(pf.getPassword());
		else if (okCxl == JOptionPane.CANCEL_OPTION) 
			return null;
		else
			return null;
	}
	
	protected static String[] showDatabeseSignOnPanel(String defaultUser)
	{
		String dbUser = null;
		String dbPasswd = null;
		JPanel p = new JPanel();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		JTextField uf = new JTextField(defaultUser);
		JPasswordField pf = new JPasswordField();
		JLabel ufl = new JLabel("User:");
		JLabel pfl = new JLabel("Password:");
		ufl.setFont(new Font(ufl.getFont().getFontName(), Font.BOLD, ufl.getFont().getSize()));
		pfl.setFont(new Font(pfl.getFont().getFontName(), Font.BOLD, pfl.getFont().getSize()));
		p.add(ufl);
		p.add(uf);
		p.add(pfl);
		p.add(pf);
	
    	int okCxl = JOptionPane.showConfirmDialog(null, p, "Database sign on", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);

    	if (okCxl == JOptionPane.OK_OPTION) 
    	{
    	  dbPasswd = new String(pf.getPassword());
    	  dbUser = new String(uf.getText());
    	}
//    	else if (okCxl == JOptionPane.CANCEL_OPTION) 
//    	{
//    		dbPasswd = null;
//    	}
    	
    	return new String[]{dbUser, dbPasswd};
	}
	
	protected static Connection getUserProvidedConnection(String connURL, String driverName, String user, String passwd) throws Exception
    {
    	Connection result = null;
    	try 
    	{
    		Class.forName(driverName).newInstance();
    	}
    	catch (Exception e)
    	{
    		System.out.println("Check classpath. Cannot load db driver: " + driverName);
    		e.printStackTrace();
    		throw e;
    	}
    	
    	try
    	{
    		result = DriverManager.getConnection(connURL, user, passwd);
    	}
    	catch (SQLException e)
    	{
    		System.out.println("Driver loaded, but cannot connect to db: " + connURL);
    		e.printStackTrace();
    		throw e;
    		
    	}
    	return result;
    }
	
	protected static String translatePLtoENG(String expressionToTransform)
	{
		Matcher m = TextProcessingUtils.plIPattern.matcher(expressionToTransform);//i -> and
		if(m.find())
			expressionToTransform = m.replaceAll(" and ");
		m = TextProcessingUtils.plLUBPattern.matcher(expressionToTransform);//lub -> or
		if(m.find())
			expressionToTransform = m.replaceAll(" or ");
		m = TextProcessingUtils.plKONIECZNIE1Pattern.matcher(expressionToTransform);//koniecznie -> some
		if(m.find())
			expressionToTransform = m.replaceAll(" some ");
		
		m = TextProcessingUtils.plNIEPattern.matcher(expressionToTransform);//nie ( -> not (
		if(m.find())
			expressionToTransform = m.replaceAll(" not (");
		do
		{
			m = TextProcessingUtils.plNIEPattern2.matcher(expressionToTransform);//(nie ( -> not (
			if(m.find())
				expressionToTransform = m.replaceFirst(" ".concat(m.group(1)).concat("not ("));
			m = TextProcessingUtils.plNIEPattern2.matcher(expressionToTransform);//(nie ( -> not (
		}
		while(m.find());
		
		return expressionToTransform;
	}

	protected static boolean checkIfContainsAnnotation(OWLClass category, OWLAnnotationProperty annotationProperty, OWLOntology ont) 
	{
		for(OWLAnnotationAssertionAxiom anAxiom : category.getAnnotationAssertionAxioms(ont))
		{
			if(anAxiom.getProperty().equals(annotationProperty))
				return true;
		}
		return false;
	}

    
}
